home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Open Source / AutoHotKey / Source / AutoHotkey104705_source.exe / source / application.h < prev    next >
Encoding:
C/C++ Source or Header  |  2007-06-10  |  7.4 KB  |  140 lines

  1. /*
  2. AutoHotkey
  3.  
  4. Copyright 2003-2007 Chris Mallett (support@autohotkey.com)
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15. */
  16.  
  17. #ifndef application_h
  18. #define application_h
  19.  
  20. #include "defines.h"
  21.  
  22. // Callers should note that using INTERVAL_UNSPECIFIED might not rest the CPU at all if there is
  23. // already at least one msg waiting in our thread's msg queue:
  24. // Use some negative value unlikely to ever be passed explicitly:
  25. #define INTERVAL_UNSPECIFIED (INT_MIN + 303)
  26. #define NO_SLEEP -1
  27. enum MessageMode {WAIT_FOR_MESSAGES, RETURN_AFTER_MESSAGES, RETURN_AFTER_MESSAGES_SPECIAL_FILTER};
  28. bool MsgSleep(int aSleepDuration = INTERVAL_UNSPECIFIED, MessageMode aMode = RETURN_AFTER_MESSAGES);
  29.  
  30. // This macro is used to Sleep without the possibility of a new hotkey subroutine being launched.
  31. // Timed subroutines will also be prevented from running while it is enabled.
  32. // It should be used when an operation needs to sleep, but doesn't want to be interrupted (suspended)
  33. // by any hotkeys the user might press during that time.  Reasons why the caller wouldn't want to
  34. // be suspended:
  35. // 1) If it's doing something with a window -- such as sending keys or clicking the mouse or trying
  36. //    to activate it -- that might get messed up if a new hotkey fires in the middle of the operation.
  37. // 2) If its a command that's still using some of its parameters that might reside in the deref buffer.
  38. //    In this case, the launching of a new hotkey would likely overwrite those values, causing
  39. //    unpredictable behavior.
  40. #define SLEEP_WITHOUT_INTERRUPTION(aSleepTime) \
  41. {\
  42.     g_AllowInterruption = false;\
  43.     MsgSleep(aSleepTime);\
  44.     g_AllowInterruption = true;\
  45. }
  46.  
  47. // Whether we should allow the script's current quasi-thread to be interrupted by
  48. // either a newly pressed hotkey or a timed subroutine that is due to be run.
  49. // Note that the 2 variables used here are independent of each other to support
  50. // the case where an uninterruptible operation such as SendKeys() happens to occur
  51. // while g.AllowThreadToBeInterrupted is true, in which case we would want the
  52. // completion of that operation to affect only the status of g_AllowInterruption,
  53. // not g.AllowThreadToBeInterrupted.
  54. #define INTERRUPTIBLE (g.AllowThreadToBeInterrupted && g_AllowInterruption && !g_MenuIsVisible)
  55. #define INTERRUPTIBLE_IN_EMERGENCY (g_AllowInterruption && !g_MenuIsVisible)
  56.  
  57. // The DISABLE_UNINTERRUPTIBLE_SUB macro below must always kill the timer if it exists -- even if
  58. // the timer hasn't expired yet.  This is because if the timer were to fire when interruptibility had
  59. // already been previously restored, it's possible that it would set g.AllowThreadToBeInterrupted
  60. // to be true even when some other code had had the opporutunity to set it to false by intent.
  61. // In other words, once g.AllowThreadToBeInterrupted is set to true the first time, it should not be
  62. // set a second time "just to be sure" because by then it may already by in use by someone else
  63. // for some other purpose.
  64. // It's possible for the SetBatchLines command to have changed the values of g_script.mUninterruptibleTime
  65. // and g_script.mUninterruptedLineCountMax since the time InitNewThread() was called.  If they were
  66. // changed so that subroutines are always interruptible, that seems to be handled correctly.
  67. // If they were changed so that subroutines are never interruptible, that seems to be okay too.
  68. // It doesn't seem like any combination of starting vs. ending interruptibility is a particular
  69. // problem, so no special handling is done here (just keep it simple).
  70. // UPDATE: g.AllowThreadToBeInterrupted is always made true even if both settings are negative,
  71. // since our callers would all want us to do it unconditionally.  This is because there's no need to
  72. // keep it false even when all subroutines are permanently uninterruptible, since it will be made
  73. // false every time a new subroutine launches.
  74. // Macro notes:
  75. // Reset in case the timer hasn't yet expired and ExecUntil() didn't get a chance to do it:
  76. // ...
  77. // Since this timer is of the type that calls a function directly, rather than placing
  78. // msgs in our msg queue, it should not be necessary to worry about removing its messages
  79. // from the msg queue.
  80. // UPDATE: The below is now the same as KILL_UNINTERRUPTIBLE_TIMER because all of its callers
  81. // have finished running the current thread (i.e. the current thread is about to be destroyed):
  82. //#define DISABLE_UNINTERRUPTIBLE_SUB \
  83. //{\
  84. //    g.AllowThreadToBeInterrupted = true;\
  85. //    KILL_UNINTERRUPTIBLE_TIMER \
  86. //}
  87. //#define DISABLE_UNINTERRUPTIBLE_SUB    KILL_UNINTERRUPTIBLE_TIMER
  88.  
  89. // Have this be dynamically resolved each time.  For example, when MsgSleep() uses this
  90. // while in mode WAIT_FOR_MESSSAGES, its msg loop should use this macro in case the
  91. // value of g_AllowInterruption changes from one iteration to the next.  Thankfully,
  92. // MS made WM_HOTKEY have a very high value, so filtering in this way should not exclude
  93. // any other important types of messages:
  94. #define MSG_FILTER_MAX (INTERRUPTIBLE ? 0 : WM_HOTKEY - 1)
  95.  
  96. // Do a true Sleep() for short sleeps on Win9x because it is much more accurate than the MsgSleep()
  97. // method on that OS, at least for when short sleeps are done on Win98SE:
  98. #define DoWinDelay \
  99.     if (g.WinDelay > -1)\
  100.     {\
  101.         if (g.WinDelay < 25 && g_os.IsWin9x())\
  102.             Sleep(g.WinDelay);\
  103.         else\
  104.             MsgSleep(g.WinDelay);\
  105.     }
  106.  
  107. #define DoControlDelay \
  108.     if (g.ControlDelay > -1)\
  109.     {\
  110.         if (g.ControlDelay < 25 && g_os.IsWin9x())\
  111.             Sleep(g.ControlDelay);\
  112.         else\
  113.             MsgSleep(g.ControlDelay);\
  114.     }
  115.  
  116. ResultType IsCycleComplete(int aSleepDuration, DWORD aStartTime, bool aAllowEarlyReturn);
  117.  
  118. // These should only be called from MsgSleep() (or something called by MsgSleep()) because
  119. // we don't want to be in the situation where a thread launched by CheckScriptTimers() returns
  120. // first to a dialog's message pump rather than MsgSleep's pump.  That's because our thread
  121. // might then have queued messages that would be stuck in the queue (due to the possible absence
  122. // of the main timer) until the dialog's msg pump ended.
  123. bool CheckScriptTimers();
  124. #define CHECK_SCRIPT_TIMERS_IF_NEEDED if (g_script.mTimerEnabledCount && CheckScriptTimers()) return_value = true; // Change the existing value only if it returned true.
  125.  
  126. void PollJoysticks();
  127. #define POLL_JOYSTICK_IF_NEEDED if (Hotkey::sJoyHotkeyCount) PollJoysticks();
  128.  
  129. bool MsgMonitor(HWND aWnd, UINT aMsg, WPARAM awParam, LPARAM alParam, MSG *apMsg, LRESULT &aMsgReply);
  130.  
  131. void InitNewThread(int aPriority, bool aSkipUninterruptible, bool aIncrementThreadCount, ActionTypeType aTypeOfFirstLine);
  132. void ResumeUnderlyingThread(global_struct *pSavedStruct, char *aSavedErrorLevel, bool aKillInterruptibleTimer);
  133.  
  134. VOID CALLBACK MsgBoxTimeout(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  135. VOID CALLBACK AutoExecSectionTimeout(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  136. VOID CALLBACK UninterruptibleTimeout(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  137. VOID CALLBACK InputTimeout(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  138.  
  139. #endif
  140.